import express from 'express';
import { prisma } from '../app';
import { asyncHandler, createError } from '../middleware/errorHandler';
import { authenticateToken, AuthRequest } from '../middleware/auth';
import { validateTodoInput, validateTodoListInput } from '../middleware/validation';

const router = express.Router();

// Todo Lists Routes

// Get all todo lists for the authenticated user
router.get('/lists', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const userId = req.user!.id;

  const todoLists = await prisma.todoList.findMany({
    where: { userId },
    include: {
      todos: {
        orderBy: { createdAt: 'desc' }
      },
      _count: {
        select: {
          todos: true
        }
      }
    },
    orderBy: { createdAt: 'asc' }
  });

  res.json({
    success: true,
    data: { todoLists }
  });
}));

// Create a new todo list
router.post('/lists', authenticateToken, validateTodoListInput, asyncHandler(async (req: AuthRequest, res) => {
  const { name } = req.body;
  const userId = req.user!.id;

  const todoList = await prisma.todoList.create({
    data: {
      name,
      userId
    },
    include: {
      todos: true,
      _count: {
        select: {
          todos: true
        }
      }
    }
  });

  res.status(201).json({
    success: true,
    message: 'Todo list created successfully',
    data: { todoList }
  });
}));

// Update a todo list
router.put('/lists/:id', authenticateToken, validateTodoListInput, asyncHandler(async (req: AuthRequest, res) => {
  const listId = parseInt(req.params.id);
  const userId = req.user!.id;
  const { name } = req.body;

  if (isNaN(listId)) {
    throw createError('Invalid list ID', 400);
  }

  // Check if list exists and belongs to user
  const existingList = await prisma.todoList.findFirst({
    where: {
      id: listId,
      userId
    }
  });

  if (!existingList) {
    throw createError('Todo list not found', 404);
  }

  const todoList = await prisma.todoList.update({
    where: { id: listId },
    data: { name },
    include: {
      todos: {
        orderBy: { createdAt: 'desc' }
      },
      _count: {
        select: {
          todos: true
        }
      }
    }
  });

  res.json({
    success: true,
    message: 'Todo list updated successfully',
    data: { todoList }
  });
}));

// Delete a todo list
router.delete('/lists/:id', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const listId = parseInt(req.params.id);
  const userId = req.user!.id;

  if (isNaN(listId)) {
    throw createError('Invalid list ID', 400);
  }

  // Check if list exists and belongs to user
  const existingList = await prisma.todoList.findFirst({
    where: {
      id: listId,
      userId
    }
  });

  if (!existingList) {
    throw createError('Todo list not found', 404);
  }

  // Delete the list (todos will be deleted due to cascade)
  await prisma.todoList.delete({
    where: { id: listId }
  });

  res.json({
    success: true,
    message: 'Todo list deleted successfully'
  });
}));

// Todos Routes

// Get all todos for a specific list
router.get('/lists/:listId/todos', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const listId = parseInt(req.params.listId);
  const userId = req.user!.id;

  if (isNaN(listId)) {
    throw createError('Invalid list ID', 400);
  }

  // Check if list exists and belongs to user
  const existingList = await prisma.todoList.findFirst({
    where: {
      id: listId,
      userId
    }
  });

  if (!existingList) {
    throw createError('Todo list not found', 404);
  }

  const todos = await prisma.todo.findMany({
    where: { listId },
    orderBy: [
      { completed: 'asc' },
      { priority: 'desc' },
      { createdAt: 'desc' }
    ]
  });

  res.json({
    success: true,
    data: { todos }
  });
}));

// Get all todos for the authenticated user (across all lists)
router.get('/', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const userId = req.user!.id;
  const { completed, priority, limit } = req.query;

  const where: any = {
    list: {
      userId
    }
  };

  if (completed !== undefined) {
    where.completed = completed === 'true';
  }

  if (priority && !isNaN(parseInt(priority as string))) {
    where.priority = parseInt(priority as string);
  }

  const queryOptions: any = {
    where,
    include: {
      list: {
        select: {
          id: true,
          name: true
        }
      }
    },
    orderBy: [
      { completed: 'asc' },
      { priority: 'desc' },
      { createdAt: 'desc' }
    ]
  };

  if (limit && !isNaN(parseInt(limit as string))) {
    queryOptions.take = parseInt(limit as string);
  }

  const todos = await prisma.todo.findMany(queryOptions);

  res.json({
    success: true,
    data: { todos }
  });
}));

// Create a new todo
router.post('/', authenticateToken, validateTodoInput, asyncHandler(async (req: AuthRequest, res) => {
  const { title, listId, dueDate, priority = 0 } = req.body;
  const userId = req.user!.id;

  let targetListId = listId;

  // If no listId provided, use the first list or create a default one
  if (!targetListId) {
    let defaultList = await prisma.todoList.findFirst({
      where: { userId },
      orderBy: { createdAt: 'asc' }
    });

    if (!defaultList) {
      defaultList = await prisma.todoList.create({
        data: {
          name: '我的任务',
          userId
        }
      });
    }

    targetListId = defaultList.id;
  } else {
    // Check if list exists and belongs to user
    const existingList = await prisma.todoList.findFirst({
      where: {
        id: targetListId,
        userId
      }
    });

    if (!existingList) {
      throw createError('Todo list not found', 404);
    }
  }

  const todo = await prisma.todo.create({
    data: {
      title,
      listId: targetListId,
      dueDate: dueDate ? new Date(dueDate) : null,
      priority: priority || 0
    },
    include: {
      list: {
        select: {
          id: true,
          name: true
        }
      }
    }
  });

  res.status(201).json({
    success: true,
    message: 'Todo created successfully',
    data: { todo }
  });
}));

// Update a todo
router.put('/:id', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const todoId = parseInt(req.params.id);
  const userId = req.user!.id;
  const { title, completed, dueDate, priority, listId } = req.body;

  if (isNaN(todoId)) {
    throw createError('Invalid todo ID', 400);
  }

  // Check if todo exists and belongs to user
  const existingTodo = await prisma.todo.findFirst({
    where: {
      id: todoId,
      list: {
        userId
      }
    }
  });

  if (!existingTodo) {
    throw createError('Todo not found', 404);
  }

  const updateData: any = {};

  if (title !== undefined) {
    if (!title || title.length < 1 || title.length > 255) {
      throw createError('Title must be between 1 and 255 characters', 400);
    }
    updateData.title = title;
  }

  if (completed !== undefined) {
    updateData.completed = Boolean(completed);
    
    // Record activity when completing a task
    if (Boolean(completed) && !existingTodo.completed) {
      const today = new Date();
      today.setHours(0, 0, 0, 0);

      await prisma.userActivity.upsert({
        where: {
          userId_date: {
            userId,
            date: today
          }
        },
        update: {
          count: {
            increment: 1
          }
        },
        create: {
          userId,
          date: today,
          count: 1
        }
      });
    }
  }

  if (dueDate !== undefined) {
    updateData.dueDate = dueDate ? new Date(dueDate) : null;
  }

  if (priority !== undefined) {
    updateData.priority = priority;
  }

  if (listId !== undefined) {
    // Check if target list exists and belongs to user
    const targetList = await prisma.todoList.findFirst({
      where: {
        id: listId,
        userId
      }
    });

    if (!targetList) {
      throw createError('Target todo list not found', 404);
    }

    updateData.listId = listId;
  }

  const todo = await prisma.todo.update({
    where: { id: todoId },
    data: updateData,
    include: {
      list: {
        select: {
          id: true,
          name: true
        }
      }
    }
  });

  res.json({
    success: true,
    message: 'Todo updated successfully',
    data: { todo }
  });
}));

// Delete a todo
router.delete('/:id', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const todoId = parseInt(req.params.id);
  const userId = req.user!.id;

  if (isNaN(todoId)) {
    throw createError('Invalid todo ID', 400);
  }

  // Check if todo exists and belongs to user
  const existingTodo = await prisma.todo.findFirst({
    where: {
      id: todoId,
      list: {
        userId
      }
    }
  });

  if (!existingTodo) {
    throw createError('Todo not found', 404);
  }

  await prisma.todo.delete({
    where: { id: todoId }
  });

  res.json({
    success: true,
    message: 'Todo deleted successfully'
  });
}));

export default router;